package net.maku.newbase.annotation.sensitive;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {

    int row;
    int endRow;
    int rowNum;
    String replace;
    SensitiveType type;

    public SensitiveSerialize(Sensitive sensitive) {
        this.row = sensitive.row();
        this.endRow = sensitive.endRow();
        this.rowNum = sensitive.rowNum();
        this.replace = sensitive.replace();
        this.type = sensitive.type();
    }

    @Override
    public void serialize(
            final String origin,
            final JsonGenerator jsonGenerator,
            final SerializerProvider serializerProvider
    ) throws IOException {
        fnType();
        fnString(origin, jsonGenerator);
    }

    @Override
    public JsonSerializer<?> createContextual(
            final SerializerProvider serializerProvider,
            final BeanProperty beanProperty
    ) throws JsonMappingException {

        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Sensitive.class);
                }
                if (sensitive != null) {
                    return new SensitiveSerialize(sensitive);
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }

    private void fnType() {
        switch (this.type) {
            case NAME:
                endRow = 0;
                break;
            case PHONE:
                endRow = 4;
                row = 3;
                break;
            case IDCARD:
                endRow = 4;
                row = 4;
                break;
            default:
        }
    }

    private void fnString(String origin, JsonGenerator jsonGenerator) throws IOException {
        String str = "";
        if (endRow >= 0) rowNum = origin.length() - row - endRow;

        for (int i = 0; i < rowNum; i++)
            str += replace;

        if (origin.length() > row) {
            String q = origin.substring(0, row);
            String h = "";
            if (origin.length() >= row + rowNum) {
                h = origin.substring(row + rowNum);
            }

            origin = new StringBuffer().append(q).append(str).append(h).toString();
        }

        jsonGenerator.writeString(origin);
    }
}
